package com.xlh.virtualization.job.delayed;

import cn.hutool.core.date.DateUtil;
import com.xlh.util.SpringContextUtil;
import com.xlh.virtualization.domain.ContainerContext;
import com.xlh.virtualization.service.ContainerService;
import com.xlh.virtualization.websocket.CourseExperimentWebsocket;
import com.xlh.virtualization.websocket.RedirectToTheoryWebsocket;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

import static com.xlh.virtualization.job.delayed.RedirectToTheoryTask.TaskTypeEnum.*;

/**
 * @author cheer
 */
public class RedirectToTheoryTask implements Delayed, Runnable {

    private static final ContainerService containerService = SpringContextUtil.getBean(ContainerService.class);

    /**
     * 通知时间 85分钟
     */
    private static final int DEFAULT_NOTICE_DELAY = 85 * 60;
    /**
     * 延时时间 60分钟
     */
    private static final int DEFAULT_DELAY_DELAY = 60 * 60;
    /**
     * 通知后停止时间5分钟
     */
    private static final int DEFAULT_STOP_DELAY = 5 * 60;

    public enum TaskTypeEnum {
        NOTICE,
        DELAY,
        STOP
    }

    private ContainerContext containerContext;

    /**
     * 任务类型
     */
    private TaskTypeEnum taskType;

    /**
     * 任务Id
     */
    private String taskId;

    /**
     * 过期时间，单位：秒
     */
    private Long expireTime;

    public RedirectToTheoryTask(ContainerContext containerContext, TaskTypeEnum taskType) {
        this.containerContext = containerContext;
        this.taskType = taskType;
        if (taskType == NOTICE) {
            this.expireTime = DateUtil.currentSeconds() + (long) DEFAULT_NOTICE_DELAY;
        } else if (taskType == DELAY) {
            this.expireTime = DateUtil.currentSeconds() + (long) DEFAULT_DELAY_DELAY;
            this.taskType = NOTICE;
        } else if (taskType == STOP) {
            this.expireTime = DateUtil.currentSeconds() + (long) DEFAULT_STOP_DELAY;
        } else {
            throw new IllegalArgumentException("非法参数");
        }
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(expireTime - DateUtil.currentSeconds(), TimeUnit.SECONDS);
    }

    @Override
    public void run() {
        String taskId = RedirectToTheoryListener.recordTable.get(containerContext);
        if (StringUtils.isNotBlank(taskId) && StringUtils.equals(this.taskId, taskId) &&
                !CourseExperimentWebsocket.isOnline(containerContext)) {
            if (taskType == NOTICE) {
                RedirectToTheoryWebsocket.notifyStopContainer(containerContext);
                RedirectToTheoryTask stopTask = new RedirectToTheoryTask(containerContext, STOP);
                stopTask.setTaskId(taskId);
                RedirectToTheoryListener.putTask(stopTask);
            } else if (taskType == STOP) {
                containerService.stopContainerByContext(containerContext);
                RedirectToTheoryListener.recordTable.remove(containerContext);
            }
        }
    }

    @Override
    public int compareTo(Delayed o) {
        if (o == this) {
            return 0;
        }
        if (o instanceof RedirectToTheoryTask) {
            RedirectToTheoryTask other = (RedirectToTheoryTask) o;
            if (expireTime < other.expireTime) {
                return -1;
            } else if (expireTime > other.expireTime) {
                return 1;
            }
        }
        return 0;
    }

    public Long getUserId() {
        return containerContext.getUserId();
    }

    public Long getContextId() {
        return containerContext.getContextId();
    }

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public ContainerContext getContainerContext() {
        return containerContext;
    }
}
